import numpy as np

x0 = np.array([-3, -1, -3, -1], dtype=np.float64)


def f(x):
    x1, x2, x3, x4 = x[0].item(), x[1].item(), x[2].item(), x[3].item()
    return sum([
        100 * (x2 - x1 * x1) ** 2,
        (1 - x1) ** 2,
        90 * (x4 - x3 * x3) ** 2,
        (1 - x3) ** 2,
        10 * (x2 + x4 - 2) ** 2,
        0.1 * (x2 - x4) ** 2
    ])


def g(x):
    x1, x2, x3, x4 = x[0].item(), x[1].item(), x[2].item(), x[3].item()
    return np.array([
        -400 * x1 * (-x1 ** 2 + x2) + 2 * x1 - 2,
        -200 * x1 ** 2 + 220.2 * x2 + 19.8 * x4 - 40,
        -360 * x3 * (-x3 ** 2 + x4) + 2 * x3 - 2,
        19.8 * x2 - 180 * x3 ** 2 + 200.2 * x4 - 40
    ], dtype=np.float64)


def h(x):
    x1, x2, x3, x4 = x[0].item(), x[1].item(), x[2].item(), x[3].item()
    return np.array([
        [1200 * x1 ** 2 - 400 * x2 + 2, -400 * x1, 0, 0],
        [-400 * x1, 220.2, 0, 19.8],
        [0, 0, 1080 * x3 ** 2 - 360 * x4 + 2, -360 * x3],
        [0, 19.8, -360 * x3, 200.2]
    ], dtype=np.float64)


def create():
    """
    Create Wood's function

    :return: x0, f, g, G
    """
    return x0, f, g, h
